;----------------------------------------------------------------------------
;input devices go here
;----------------------------------------------------------------------------
.486p
.model flat
.code

        include file.h
        include kb.h
        include empty.h
        include mouse.h
        include equates.h
        include config.h
        include joystick.h
        include 6502.h
        include data.h

        public getinput
        public joy0_W
        public joy1_W
        public joy0_R
        public joy1_R
        public serialload
        public zapload
        public zapread
        public paddleload
        public paddleread
        public ppadread
        public ppadload
        public serialread
        public serial0mask
        public serial1mask
        public control0load
        public control1load
        public control0data
        public control1data
        public ctrlsetup
        public zapperptr
;----------------------------------------------------------------------------
getinput:;      call every frame
;----------------------------------------------------------------------------
        mov [zapperptr],0                       ;hide crosshairs from ppu
        cmp [playhandle],0                      ;playing a movie?
        jne playmovie

        clc                                     ;CF=1 if eax already holds data
        mov edi,offset control0config           ;edi=config
        call [control0load]                     ;get control state in eax
        mov [control0data],eax
        clc
        mov edi,offset control1config
        call [control1load]
        mov [control1data],eax

        mov eax,[control0data]
        mov ebx,[control1data]
        cmp [snsshandle],0                      ;saving a movie?
        jne writemovie
        ret
;----------------------------------------------------------------------------
joy0_W:;        4016
;----------------------------------------------------------------------------
        mov [strobe],3
        ret
;----------------------------------------------------------------------------
joy1_W:;        $4017
;----------------------------------------------------------------------------
        ret
;----------------------------------------------------------------------------
joy0_R:;        $4016
;----------------------------------------------------------------------------
        jmp [control0read]
;----------------------------------------------------------------------------
joy1_R:;        $4017
;----------------------------------------------------------------------------
        jmp [control1read]
;----------------------------------------------------------------------------
serialread:
;----------------------------------------------------------------------------
        and edi,1
        jnz serial1read
        test [strobe],1
        jz sr00

        and [strobe],not 1
        mov eax,[control0data]
        or eax,80000h
        mov [serial0data],eax
sr00:
        mov al,[kb_table+KB_TILDE]      ;coin
        and al,40h
        shr [serial0data],1
        adc al,[serial0mask]

        ret
serial1read:;- - - - - - - - - - - - - -
        test [strobe],2
        jz sr10

        and [strobe],not 2
        mov eax,[control1data]
        or eax,40000h
        mov [serial1data],eax
sr10:
        xor al,al
        shr [serial1data],1
        adc al,[serial1mask]
        ret
;----------------------------------------------------------------------------
serialload:;    dual input for quad controller
;----------------------------------------------------------------------------
        jc ql0
        call [edi+28]           ;should return with edi intact
        add edi,64              ;(c=0)
        push eax
        call [edi+28]           ;JOYPAD types have their loaders in config+28
        pop edi
        shl eax,8
        or eax,edi
ql0:    ret
;----------------------------------------------------------------------------
unpluggedload:;     (serial) not plugged in
;----------------------------------------------------------------------------
        jc up0                  ;allow joypad data thru from savestates
        xor eax,eax
up0:    ret
;----------------------------------------------------------------------------
kbload:;        joypad from keyboard
;       in:
;               edi=config ptr
;       out:
;               eax=
;----------------------------------------------------------------------------
        jc kl0
        push ebx
        xor ebp,ebp     ;ebp=temp holder
        xor eax,eax     ;eax=kbd ptr

        mov al,[a_btn+edi]
        mov al,[kb_table+eax]
        and al,01h
        or ebp,eax
        mov al,[b_btn+edi]
        mov al,[kb_table+eax]
        and al,02h
        or ebp,eax
        mov al,[sel+edi]
        mov al,[kb_table+eax]
        and al,04h
        or ebp,eax
        mov al,[start+edi]
        mov al,[kb_table+eax]
        and al,08h
        or ebp,eax

        mov al,[up+edi]
        mov al,[kb_table+eax]
        mov bl,al
        and al,10h
        or ebp,eax
        mov al,[down+edi]
        mov al,[kb_table+eax]
        and bl,al
        and al,20h
        or ebp,eax
        and ebx,30h
        xor ebp,ebx

        mov al,[left+edi]
        mov al,[kb_table+eax]
        mov bl,al
        and al,40h
        or ebp,eax
        mov al,[right+edi]
        mov al,[kb_table+eax]
        and bl,al
        and al,80h
        or ebp,eax
        and ebx,0c0h
        xor ebp,ebx

        mov eax,ebp
        pop ebx
kl0:
        ret
;----------------------------------------------------------------------------
joystick0load:;     joypad from joystick 0
;----------------------------------------------------------------------------
        jc j09
        test [joyread],1
        je j08
        or [joymask],00110000b
        call joy_load                   ;update joystick data periodically
        and [joyread],not 1
j08:
        xor eax,eax
        xor ebp,ebp

        mov al,[joy_a+edi]                      ;keyboard stuff
        cmp al,4
        jb j00
        mov al,[kb_table+eax]
        and al,01h
        or ebp,eax
        mov al,[joy_b+edi]
        cmp al,4
        jb j01
j04:    mov al,[kb_table+eax]
        and al,02h
        or ebp,eax
        mov al,[joy_sel+edi]
        cmp al,4
        jb j02
j05:    mov al,[kb_table+eax]
        and al,04h
        or ebp,eax
        mov al,[joy_start+edi]
        cmp al,4
        jb j03
j06:    mov al,[kb_table+eax]
        and al,08h
        or ebp,eax
        jmp j07

j00:    mov al,byte ptr [joybuttons+eax]                 ;joystick stuff
        and al,01h
        or ebp,eax
        mov al,[joy_b+edi]
        cmp al,3
        ja j04
j01:    mov al,byte ptr [joybuttons+eax]
        and al,02h
        or ebp,eax
        mov al,[joy_sel+edi]
        cmp al,3
        ja j05
j02:    mov al,byte ptr [joybuttons+eax]
        and al,04h
        or ebp,eax
        mov al,[joy_start+edi]
        cmp al,3
        ja j06
j03:    mov al,byte ptr [joybuttons+eax]
        and al,08h
        or ebp,eax
j07:
        mov eax,[joy0axis]
        or eax,ebp
j09:    ret
;----------------------------------------------------------------------------
joystick1load:;      joypad from joystick 1
;----------------------------------------------------------------------------
        jc j19
        test [joyread],2
        je j18
        or [joymask],11000000b
        call joy_load
        and [joyread],not 2
j18:
        xor eax,eax
        xor ebp,ebp

        mov al,[joy_a+edi]                      ;keyboard stuff
        cmp al,4
        jb j10
        mov al,[kb_table+eax]
        and al,01h
        or ebp,eax
        mov al,[joy_b+edi]
        cmp al,4
        jb j11
j14:    mov al,[kb_table+eax]
        and al,02h
        or ebp,eax
        mov al,[joy_sel+edi]
        cmp al,4
        jb j12
j15:    mov al,[kb_table+eax]
        and al,04h
        or ebp,eax
        mov al,[joy_start+edi]
        cmp al,4
        jb j13
j16:    mov al,[kb_table+eax]
        and al,08h
        or ebp,eax
        jmp j17

j10:    mov al,byte ptr [joybuttons+eax]                 ;joystick stuff
        and al,01h
        or ebp,eax
        mov al,[joy_b+edi]
        cmp al,3
        ja j14
j11:    mov al,byte ptr [joybuttons+eax]
        and al,02h
        or ebp,eax
        mov al,[joy_sel+edi]
        cmp al,3
        ja j15
j12:    mov al,byte ptr [joybuttons+eax]
        and al,04h
        or ebp,eax
        mov al,[joy_start+edi]
        cmp al,3
        ja j16
j13:    mov al,byte ptr [joybuttons+eax]
        and al,08h
        or ebp,eax
j17:
        mov eax,[joy1axis]
        or eax,ebp
j19:    ret
;----------------------------------------------------------------------------
snespadload:;
;       in:
;               edi=config ptr
;       out:
;               eax=
;----------------------------------------------------------------------------
        jc snes0
        push ecx
        push edx

        mov edx,[edi]
        mov cx,[edi+4]
        mov al,11111001b
        out dx,al
        out dx,al
        out dx,al
        mov al,11111011b
        out dx,al
        out dx,al
        out dx,al

        call snes1
        call snes1
        call snes1
        call snes1
        call snes1
        call snes1
        call snes1
        call snes1

        mov al,0
        out dx,al
        pop edx
        pop ecx
        mov eax,ebp
        shr eax,24
snes0:
        ret
snes1:
        mov al,11111000b
        out dx,al
        out dx,al
        out dx,al
        inc edx
        in al,dx
        xor al,ch
        shr al,cl
        rcr ebp,1
        dec edx
        mov al,11111001b
        out dx,al
        out dx,al
        out dx,al
        ret
;----------------------------------------------------------------------------
paddleload:;
;----------------------------------------------------------------------------
        jc pl0
        mov al,byte ptr [mouseX]
        mov ah,[mousebutton]
pl0:        
        and [serial0mask],not 2
        test ah,1
        jz pl1
        or [serial0mask],2
pl1:
        ret
;----------------------------------------------------------------------------
paddleread:;
;----------------------------------------------------------------------------
        test [strobe],2
        jz pd0
        and [strobe],not 2

        mov eax,[control1data]
        xor al,0ffh
        shl eax,24
        mov [serial1data],eax
pd0:
        xor eax,eax
        shl [serial1data],1
        adc al,0
        add al,al
        ret
;----------------------------------------------------------------------------
zapload:;
;----------------------------------------------------------------------------
        jc zl0
        mov ah,[mousebutton]
        mov al,byte ptr [mouseY]
        shl eax,8
        mov al,byte ptr [mouseX]

        cmp [mouseX],255
        ja zl2
        cmp [mouseY],240
        jb zl0
zl2:    or eax,0ffffh
zl0:
        mov ebp,eax                             ;save for later..
        xor edi,edi
        and eax,0ffffh
        and ebp,1ffffh
        cmp ah,239
        ja zl1
        mov edi,eax
        shr eax,8
        lea edi,[vscreen+8+edi+eax*8]
zl1:    mov [zapperptr],edi                     ;set screen ptr

        mov eax,ebp
        shr eax,8                               ;trigger:
        mov al,[lastbutton]
        xor al,ah
        and al,ah
        mov [lastbutton],ah
        jz zl3
        mov eax,[framecount]
        inc eax
        mov [triggertimeout],eax
zl3:
        mov eax,ebp                             ;return zapper data
        ret
;----------------------------------------------------------------------------
zapread:;
;----------------------------------------------------------------------------
        mov edi,[zapperptr]
        mov ebp,[palmap]
        or edi,edi                              ;out of range?
        jz z0
        movzx eax,byte ptr [edi]                ;read pixel
        cmp al,40h
        jb z64
        mov al,[vram+3f00h+eax-40h]             ;(al=palette#)
z64:    cmp byte ptr [ebp+eax],0fh              ;(al=color#)
        je z0                                   ;black?
        xor al,al                                 ;hit
        jmp z1
z0:
        mov al,08h                                ;no hit
z1:
        mov edi,[triggertimeout]
        cmp edi,[framecount]
        jb z2
        or al,10h
z2:
        ret
;----------------------------------------------------------------------------
vszapread:;
;----------------------------------------------------------------------------
        test [strobe],1
        jz vs0

        and [strobe],not 1
        call zapread
        shl al,3
        xor al,7fh
        mov [serial0data],eax
vs0:
        mov al,[kb_table+KB_TILDE]      ;coin
        and al,40h
        shr [serial0data],1
        adc al,[serial0mask]
        ret
;----------------------------------------------------------------------------
ppadload:;
;----------------------------------------------------------------------------
        jc ppl0
        xor eax,eax

        sar [kb_table+KB_8PAD],1
        rcl al,1
        sar [kb_table+KB_9PAD],1
        rcl al,1
        sar [kb_table+KB_6PAD],1
        rcl al,1
        sar [kb_table+KB_5PAD],1
        rcl al,1
        sar [kb_table+KB_3PAD],1
        rcl al,1
        sar [kb_table+KB_2PAD],1
        rcl al,1
        sar [kb_table+KB_1PAD],1
        rcl al,1
        sar [kb_table+KB_4PAD],1
        rcl al,1

        sar [kb_table+KB_DIVPAD],1
        rcl ah,1
        sar [kb_table+KB_STARPAD],1
        rcl ah,1
        sar [kb_table+KB_7PAD],1
        rcl ah,1
        sar [kb_table+KB_NUMLOCK],1
        rcl ah,1
ppl0:
        ret
;----------------------------------------------------------------------------
ppadread:;
;----------------------------------------------------------------------------
        test [strobe],2
        jz ppr0

        and [strobe],not 2
        mov eax,[control1data]
        mov [serial1data],eax
ppr0:
        xor al,al
        shr byte ptr [serial1data+1],1
        rcl al,1
        shr byte ptr [serial1data],1
        rcl al,4

        ret
;----------------------------------------------------------------------------
ctrlsetup:;     keep this separate so it can be changed by savestates
;----------------------------------------------------------------------------        
        xor ecx,ecx                     ;serial details..
        mov esi,offset control0config+28
cset4:  movzx edi,[inputtype+ecx]
        mov eax,[inputtbl+edi*4]
        mov [esi],eax
        add esi,32                      ;(+config size)
        inc cl
        cmp cl,4
        jb cset4                    ;- - - - - - - -

        movzx edi,[control0type]        ;set read/load routines from type
        cmp edi,QUAD
        jne cset2
        mov edi,JOYPAD
        mov [control0type],JOYPAD       ;don't want quad
cset2:  mov eax,[ctrltbl+edi*8]
        mov ebx,[ctrltbl+4+edi*8]
        mov [control0read],eax
        mov [control0load],ebx

        cmp edi,JOYPAD                  ;if type0=joypad and type2=nothing,
        jne cset0                       ;replace quad load with regular load
        cmp [inputtype+2],UNPLUGGED
        jne cset0
        mov eax,dword ptr [control0config+28]
        mov [control0load],eax
cset0:                              ;- - - - - - - -
        movzx edi,[control1type]        ;likewise..
        cmp edi,QUAD
        jne cset3
        mov edi,JOYPAD
        mov [control1type],JOYPAD
cset3:  mov eax,[ctrltbl+edi*8]
        mov ebx,[ctrltbl+4+edi*8]
        mov [control1read],eax
        mov [control1load],ebx

        cmp edi,JOYPAD
        jne cset1
        cmp [inputtype+3],UNPLUGGED
        jne cset1
        mov eax,dword ptr [control1config+28]
        mov [control1load],eax
cset1:
        ret
;----------------------------------------------------------------------------

                align 4

ctrltbl         dd serialread,serialload        ;ordered by SNSS types-
                dd paddleread,paddleload        ;paddle
                dd zapread,zapload              ;zapper
                dd ?,?                          ;quad (don't use)
                dd paddleread,paddleload        ;ROB
                dd ppadread,ppadload            ;powerpad
                dd vszapread,zapload            ;VS zapper

inputtbl        dd unpluggedload                ;ordered by inputtype types
                dd kbload
                dd joystick0load
                dd joystick1load
                dd snespadload

control0load    dd ?            ;called every frame
control1load    dd ?

control0read    dd ?            ;called on 4016/7 read
control1read    dd ?

control0data    dd ?            ;controller state, updated each frame
control1data    dd ?            

serial0data     dd ?            ;for serial reading
serial1data     dd ?

zapperptr       dd 0            ;vscreen pointer for zapper
triggertimeout  dd ?

serial0mask     db ?            ;for VS dips, etc
serial1mask     db ?
lastbutton      db ?            ;(for zapper)
strobe          db ?

kbconfig struc
        left db ?
        up db ?
        right db ?
        down db ?
        sel db ?
        start db ?
        b_btn db ?
        a_btn db ?
ends

joyconfig struc
        joy_sel         db ?
        joy_start       db ?
        joy_b           db ?
        joy_a           db ?
ends

;----------------------------------------------------------------------------
        end
